{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "kR-4eNdK6lYS"
   },
   "source": [
    "Deep Learning\n",
    "=============\n",
    "\n",
    "Assignment 3\n",
    "------------\n",
    "\n",
    "Previously in `2_fullyconnected.ipynb`, you trained a logistic regression and a neural network model.\n",
    "\n",
    "The goal of this assignment is to explore regularization techniques."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     }
    },
    "colab_type": "code",
    "collapsed": true,
    "id": "JLpLa8Jt7Vu4"
   },
   "outputs": [],
   "source": [
    "# These are all the modules we'll be using later. Make sure you can import them\n",
    "# before proceeding further.\n",
    "from __future__ import print_function\n",
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from six.moves import cPickle as pickle"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "1HrCK6e17WzV"
   },
   "source": [
    "First reload the data we generated in _notmist.ipynb_."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     },
     "output_extras": [
      {
       "item_id": 1
      }
     ]
    },
    "colab_type": "code",
    "collapsed": false,
    "executionInfo": {
     "elapsed": 11777,
     "status": "ok",
     "timestamp": 1449849322348,
     "user": {
      "color": "",
      "displayName": "",
      "isAnonymous": false,
      "isMe": true,
      "permissionId": "",
      "photoUrl": "",
      "sessionId": "0",
      "userId": ""
     },
     "user_tz": 480
    },
    "id": "y3-cj1bpmuxc",
    "outputId": "e03576f1-ebbe-4838-c388-f1777bcc9873"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training set (200000, 28, 28) (200000,)\n",
      "Validation set (10000, 28, 28) (10000,)\n",
      "Test set (10000, 28, 28) (10000,)\n"
     ]
    }
   ],
   "source": [
    "pickle_file = 'notMNIST.pickle'\n",
    "\n",
    "with open(pickle_file, 'rb') as f:\n",
    "    save = pickle.load(f)\n",
    "    train_dataset = save['train_dataset']\n",
    "    train_labels = save['train_labels']\n",
    "    valid_dataset = save['valid_dataset']\n",
    "    valid_labels = save['valid_labels']\n",
    "    test_dataset = save['test_dataset']\n",
    "    test_labels = save['test_labels']\n",
    "    del save  # hint to help gc free up memory\n",
    "    print('Training set', train_dataset.shape, train_labels.shape)\n",
    "    print('Validation set', valid_dataset.shape, valid_labels.shape)\n",
    "    print('Test set', test_dataset.shape, test_labels.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "L7aHrm6nGDMB"
   },
   "source": [
    "Reformat into a shape that's more adapted to the models we're going to train:\n",
    "- data as a flat matrix,\n",
    "- labels as float 1-hot encodings."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     },
     "output_extras": [
      {
       "item_id": 1
      }
     ]
    },
    "colab_type": "code",
    "collapsed": false,
    "executionInfo": {
     "elapsed": 11728,
     "status": "ok",
     "timestamp": 1449849322356,
     "user": {
      "color": "",
      "displayName": "",
      "isAnonymous": false,
      "isMe": true,
      "permissionId": "",
      "photoUrl": "",
      "sessionId": "0",
      "userId": ""
     },
     "user_tz": 480
    },
    "id": "IRSyYiIIGIzS",
    "outputId": "3f8996ee-3574-4f44-c953-5c8a04636582"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training set (200000, 784) (200000, 10)\n",
      "Validation set (10000, 784) (10000, 10)\n",
      "Test set (10000, 784) (10000, 10)\n"
     ]
    }
   ],
   "source": [
    "image_size = 28\n",
    "num_labels = 10\n",
    "\n",
    "def reformat(dataset, labels):\n",
    "    dataset = dataset.reshape((-1, image_size * image_size)).astype(np.float32)\n",
    "    # Map 2 to [0.0, 1.0, 0.0 ...], 3 to [0.0, 0.0, 1.0 ...]\n",
    "    labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32)\n",
    "    return dataset, labels\n",
    "train_dataset, train_labels = reformat(train_dataset, train_labels)\n",
    "valid_dataset, valid_labels = reformat(valid_dataset, valid_labels)\n",
    "test_dataset, test_labels = reformat(test_dataset, test_labels)\n",
    "print('Training set', train_dataset.shape, train_labels.shape)\n",
    "print('Validation set', valid_dataset.shape, valid_labels.shape)\n",
    "print('Test set', test_dataset.shape, test_labels.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     }
    },
    "colab_type": "code",
    "collapsed": true,
    "id": "RajPLaL_ZW6w"
   },
   "outputs": [],
   "source": [
    "def accuracy(predictions, labels):\n",
    "    return (100.0 * np.sum(np.argmax(predictions, 1) == np.argmax(labels, 1)) / predictions.shape[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "sgLbUAQ1CW-1"
   },
   "source": [
    "---\n",
    "Problem 1\n",
    "---------\n",
    "\n",
    "Introduce and tune L2 regularization for both logistic and neural network models. Remember that L2 amounts to adding a penalty on the norm of the weights to the loss. In TensorFlow, you can compute the L2 loss for a tensor `t` using `nn.l2_loss(t)`. The right amount of regularization should improve your validation / test accuracy.\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3 align='Left'>Logistic</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "\n",
    "graph = tf.Graph()\n",
    "with graph.as_default():\n",
    "\n",
    "    # Input data. For the training data, we use a placeholder that will be fed\n",
    "    # at run time with a training minibatch.\n",
    "    tf_train_dataset = tf.placeholder(tf.float32,\n",
    "                                    shape=(batch_size, image_size * image_size))\n",
    "    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))\n",
    "    tf_valid_dataset = tf.constant(valid_dataset)\n",
    "    tf_test_dataset = tf.constant(test_dataset)\n",
    "    beta_regul = tf.placeholder(tf.float32)\n",
    "    \n",
    "    # Variables.\n",
    "    weights = tf.Variable(\n",
    "    tf.truncated_normal([image_size * image_size, num_labels]))\n",
    "    biases = tf.Variable(tf.zeros([num_labels]))\n",
    "  \n",
    "    # Training computation.\n",
    "    logits = tf.matmul(tf_train_dataset, weights) + biases\n",
    "    loss = tf.reduce_mean(\n",
    "    tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels)) + beta_regul * tf.nn.l2_loss(weights)\n",
    "  \n",
    "    # Optimizer.\n",
    "    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)\n",
    "  \n",
    "    # Predictions for the training, validation, and test data.\n",
    "    train_prediction = tf.nn.softmax(logits)\n",
    "    valid_prediction = tf.nn.softmax(\n",
    "    tf.matmul(tf_valid_dataset, weights) + biases)\n",
    "    test_prediction = tf.nn.softmax(tf.matmul(tf_test_dataset, weights) + biases)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialized\n",
      "Minibatch loss at step 0: 21.262445\n",
      "Minibatch accuracy: 11.7%\n",
      "Validation accuracy: 12.9%\n",
      "Minibatch loss at step 500: 3.461964\n",
      "Minibatch accuracy: 71.9%\n",
      "Validation accuracy: 76.1%\n",
      "Minibatch loss at step 1000: 1.686536\n",
      "Minibatch accuracy: 77.3%\n",
      "Validation accuracy: 78.2%\n",
      "Minibatch loss at step 1500: 1.417062\n",
      "Minibatch accuracy: 75.8%\n",
      "Validation accuracy: 80.4%\n",
      "Minibatch loss at step 2000: 1.081537\n",
      "Minibatch accuracy: 81.2%\n",
      "Validation accuracy: 80.2%\n",
      "Minibatch loss at step 2500: 0.977062\n",
      "Minibatch accuracy: 77.3%\n",
      "Validation accuracy: 81.8%\n",
      "Minibatch loss at step 3000: 0.742881\n",
      "Minibatch accuracy: 80.5%\n",
      "Validation accuracy: 81.7%\n",
      "Minibatch loss at step 3500: 0.586915\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 81.7%\n",
      "Minibatch loss at step 4000: 0.857781\n",
      "Minibatch accuracy: 78.1%\n",
      "Validation accuracy: 82.2%\n",
      "Minibatch loss at step 4500: 0.604987\n",
      "Minibatch accuracy: 85.2%\n",
      "Validation accuracy: 82.2%\n",
      "Minibatch loss at step 5000: 0.525759\n",
      "Minibatch accuracy: 84.4%\n",
      "Validation accuracy: 82.1%\n",
      "Minibatch loss at step 5500: 0.960533\n",
      "Minibatch accuracy: 72.7%\n",
      "Validation accuracy: 82.2%\n",
      "Minibatch loss at step 6000: 0.727640\n",
      "Minibatch accuracy: 76.6%\n",
      "Validation accuracy: 82.0%\n",
      "Minibatch loss at step 6500: 1.029910\n",
      "Minibatch accuracy: 75.8%\n",
      "Validation accuracy: 81.1%\n",
      "Minibatch loss at step 7000: 0.720594\n",
      "Minibatch accuracy: 79.7%\n",
      "Validation accuracy: 82.4%\n",
      "Minibatch loss at step 7500: 0.716992\n",
      "Minibatch accuracy: 82.8%\n",
      "Validation accuracy: 81.7%\n",
      "Minibatch loss at step 8000: 0.608796\n",
      "Minibatch accuracy: 84.4%\n",
      "Validation accuracy: 82.1%\n",
      "Minibatch loss at step 8500: 0.668166\n",
      "Minibatch accuracy: 82.0%\n",
      "Validation accuracy: 81.7%\n",
      "Minibatch loss at step 9000: 0.552264\n",
      "Minibatch accuracy: 85.9%\n",
      "Validation accuracy: 82.0%\n",
      "Minibatch loss at step 9500: 0.804723\n",
      "Minibatch accuracy: 75.8%\n",
      "Validation accuracy: 81.4%\n",
      "Test accuracy: 88.5%\n"
     ]
    }
   ],
   "source": [
    "num_steps = 10000\n",
    "\n",
    "with tf.Session(graph=graph) as session:\n",
    "    tf.initialize_all_variables().run()\n",
    "    print(\"Initialized\")\n",
    "    for step in range(num_steps):\n",
    "        # Pick an offset within the training data, which has been randomized.\n",
    "        # Note: we could use better randomization across epochs.\n",
    "        offset = (step * batch_size) % (train_labels.shape[0] - batch_size)\n",
    "        # Generate a minibatch.\n",
    "        batch_data = train_dataset[offset:(offset + batch_size), :]\n",
    "        batch_labels = train_labels[offset:(offset + batch_size), :]\n",
    "        # Prepare a dictionary telling the session where to feed the minibatch.\n",
    "        # The key of the dictionary is the placeholder node of the graph to be fed,\n",
    "        # and the value is the numpy array to feed to it.\n",
    "        feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels, beta_regul : 1e-3}\n",
    "        _, l, predictions = session.run(\n",
    "          [optimizer, loss, train_prediction], feed_dict=feed_dict)\n",
    "        if (step % 500 == 0):\n",
    "            print(\"Minibatch loss at step %d: %f\" % (step, l))\n",
    "            print(\"Minibatch accuracy: %.1f%%\" % accuracy(predictions, batch_labels))\n",
    "            print(\"Validation accuracy: %.1f%%\" % accuracy(valid_prediction.eval(), valid_labels))\n",
    "    print(\"Test accuracy: %.1f%%\" % accuracy(test_prediction.eval(), test_labels))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3 align='Left'>1 Layer Neural Network</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "num_hidden_nodes = 1024\n",
    "\n",
    "graph = tf.Graph()\n",
    "with graph.as_default():\n",
    "\n",
    "    # Input data. For the training data, we use a placeholder that will be fed\n",
    "    # at run time with a training minibatch.\n",
    "    tf_train_dataset = tf.placeholder(tf.float32,\n",
    "                                    shape=(batch_size, image_size * image_size))\n",
    "    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))\n",
    "    tf_valid_dataset = tf.constant(valid_dataset)\n",
    "    tf_test_dataset = tf.constant(test_dataset)\n",
    "    beta_regul = tf.placeholder(tf.float32)\n",
    "  \n",
    "    # Variables.\n",
    "    weights1 = tf.Variable(tf.truncated_normal([image_size * image_size, num_hidden_nodes]))\n",
    "    biases1 = tf.Variable(tf.zeros([num_hidden_nodes]))\n",
    "    weights2 = tf.Variable(tf.truncated_normal([num_hidden_nodes, num_labels]))\n",
    "    biases2 = tf.Variable(tf.zeros([num_labels]))\n",
    "  \n",
    "    # Training computation.\n",
    "    lay1_train = tf.nn.relu(tf.matmul(tf_train_dataset, weights1) + biases1)\n",
    "    logits = tf.matmul(lay1_train, weights2) + biases2\n",
    "    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels)) + \\\n",
    "      beta_regul * (tf.nn.l2_loss(weights1) + tf.nn.l2_loss(weights2))\n",
    "  \n",
    "    # Optimizer.\n",
    "    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)\n",
    "  \n",
    "    # Predictions for the training, validation, and test data.\n",
    "    train_prediction = tf.nn.softmax(logits)\n",
    "    lay1_valid = tf.nn.relu(tf.matmul(tf_valid_dataset, weights1) + biases1)\n",
    "    valid_prediction = tf.nn.softmax(tf.matmul(lay1_valid, weights2) + biases2)\n",
    "    lay1_test = tf.nn.relu(tf.matmul(tf_test_dataset, weights1) + biases1)\n",
    "    test_prediction = tf.nn.softmax(tf.matmul(lay1_test, weights2) + biases2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialized\n",
      "Minibatch loss at step 0: 649.972778\n",
      "Minibatch accuracy: 11.7%\n",
      "Validation accuracy: 31.3%\n",
      "Minibatch loss at step 500: 193.815109\n",
      "Minibatch accuracy: 76.6%\n",
      "Validation accuracy: 79.0%\n",
      "Minibatch loss at step 1000: 114.571594\n",
      "Minibatch accuracy: 79.7%\n",
      "Validation accuracy: 82.1%\n",
      "Minibatch loss at step 1500: 69.223549\n",
      "Minibatch accuracy: 77.3%\n",
      "Validation accuracy: 83.8%\n",
      "Minibatch loss at step 2000: 41.467789\n",
      "Minibatch accuracy: 82.8%\n",
      "Validation accuracy: 85.7%\n",
      "Minibatch loss at step 2500: 25.579798\n",
      "Minibatch accuracy: 81.2%\n",
      "Validation accuracy: 86.5%\n",
      "Minibatch loss at step 3000: 15.476299\n",
      "Minibatch accuracy: 87.5%\n",
      "Validation accuracy: 87.2%\n",
      "Minibatch loss at step 3500: 9.543326\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 87.5%\n",
      "Minibatch loss at step 4000: 6.172801\n",
      "Minibatch accuracy: 84.4%\n",
      "Validation accuracy: 88.3%\n",
      "Minibatch loss at step 4500: 3.708045\n",
      "Minibatch accuracy: 93.8%\n",
      "Validation accuracy: 88.7%\n",
      "Minibatch loss at step 5000: 2.455110\n",
      "Minibatch accuracy: 91.4%\n",
      "Validation accuracy: 88.6%\n",
      "Minibatch loss at step 5500: 1.920115\n",
      "Minibatch accuracy: 83.6%\n",
      "Validation accuracy: 88.6%\n",
      "Minibatch loss at step 6000: 1.207688\n",
      "Minibatch accuracy: 91.4%\n",
      "Validation accuracy: 88.2%\n",
      "Minibatch loss at step 6500: 1.141730\n",
      "Minibatch accuracy: 82.0%\n",
      "Validation accuracy: 88.4%\n",
      "Minibatch loss at step 7000: 0.782690\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 88.4%\n",
      "Minibatch loss at step 7500: 0.691048\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 88.8%\n",
      "Minibatch loss at step 8000: 0.492408\n",
      "Minibatch accuracy: 92.2%\n",
      "Validation accuracy: 88.4%\n",
      "Minibatch loss at step 8500: 0.502542\n",
      "Minibatch accuracy: 91.4%\n",
      "Validation accuracy: 88.5%\n",
      "Minibatch loss at step 9000: 0.470387\n",
      "Minibatch accuracy: 91.4%\n",
      "Validation accuracy: 88.5%\n",
      "Minibatch loss at step 9500: 0.579859\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 88.4%\n",
      "Test accuracy: 94.4%\n"
     ]
    }
   ],
   "source": [
    "num_steps = 10000\n",
    "\n",
    "with tf.Session(graph=graph) as session:\n",
    "    tf.initialize_all_variables().run()\n",
    "    print(\"Initialized\")\n",
    "    for step in range(num_steps):\n",
    "        # Pick an offset within the training data, which has been randomized.\n",
    "        # Note: we could use better randomization across epochs.\n",
    "        offset = (step * batch_size) % (train_labels.shape[0] - batch_size)\n",
    "        # Generate a minibatch.\n",
    "        batch_data = train_dataset[offset:(offset + batch_size), :]\n",
    "        batch_labels = train_labels[offset:(offset + batch_size), :]\n",
    "        # Prepare a dictionary telling the session where to feed the minibatch.\n",
    "        # The key of the dictionary is the placeholder node of the graph to be fed,\n",
    "        # and the value is the numpy array to feed to it.\n",
    "        feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels, beta_regul : 1e-3}\n",
    "        _, l, predictions = session.run(\n",
    "          [optimizer, loss, train_prediction], feed_dict=feed_dict)\n",
    "        if (step % 500 == 0):\n",
    "            print(\"Minibatch loss at step %d: %f\" % (step, l))\n",
    "            print(\"Minibatch accuracy: %.1f%%\" % accuracy(predictions, batch_labels))\n",
    "            print(\"Validation accuracy: %.1f%%\" % accuracy(valid_prediction.eval(), valid_labels))\n",
    "    print(\"Test accuracy: %.1f%%\" % accuracy(test_prediction.eval(), test_labels))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "na8xX2yHZzNF"
   },
   "source": [
    "---\n",
    "Problem 2\n",
    "---------\n",
    "Let's demonstrate an extreme case of overfitting. Restrict your training data to just a few batches. What happens?\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "num_hidden_nodes = 1024\n",
    "\n",
    "graph = tf.Graph()\n",
    "with graph.as_default():\n",
    "\n",
    "    # Input data. For the training data, we use a placeholder that will be fed\n",
    "    # at run time with a training minibatch.\n",
    "    tf_train_dataset = tf.placeholder(tf.float32,\n",
    "                                    shape=(batch_size, image_size * image_size))\n",
    "    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))\n",
    "    tf_valid_dataset = tf.constant(valid_dataset)\n",
    "    tf_test_dataset = tf.constant(test_dataset)\n",
    "    beta_regul = tf.placeholder(tf.float32)\n",
    "  \n",
    "    # Variables.\n",
    "    weights1 = tf.Variable(tf.truncated_normal([image_size * image_size, num_hidden_nodes]))\n",
    "    biases1 = tf.Variable(tf.zeros([num_hidden_nodes]))\n",
    "    weights2 = tf.Variable(tf.truncated_normal([num_hidden_nodes, num_labels]))\n",
    "    biases2 = tf.Variable(tf.zeros([num_labels]))\n",
    "  \n",
    "    # Training computation.\n",
    "    lay1_train = tf.nn.relu(tf.matmul(tf_train_dataset, weights1) + biases1)\n",
    "    logits = tf.matmul(lay1_train, weights2) + biases2\n",
    "    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels))\n",
    "  \n",
    "    # Optimizer.\n",
    "    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)\n",
    "  \n",
    "    # Predictions for the training, validation, and test data.\n",
    "    train_prediction = tf.nn.softmax(logits)\n",
    "    lay1_valid = tf.nn.relu(tf.matmul(tf_valid_dataset, weights1) + biases1)\n",
    "    valid_prediction = tf.nn.softmax(tf.matmul(lay1_valid, weights2) + biases2)\n",
    "    lay1_test = tf.nn.relu(tf.matmul(tf_test_dataset, weights1) + biases1)\n",
    "    test_prediction = tf.nn.softmax(tf.matmul(lay1_test, weights2) + biases2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialized\n",
      "Minibatch loss at step 0: 663.570618\n",
      "Minibatch accuracy: 7.8%\n",
      "Validation accuracy: 27.2%\n",
      "Minibatch loss at step 2: 1345.445923\n",
      "Minibatch accuracy: 51.6%\n",
      "Validation accuracy: 47.0%\n",
      "Minibatch loss at step 4: 576.916565\n",
      "Minibatch accuracy: 71.1%\n",
      "Validation accuracy: 53.6%\n",
      "Minibatch loss at step 6: 383.797424\n",
      "Minibatch accuracy: 86.7%\n",
      "Validation accuracy: 60.3%\n",
      "Minibatch loss at step 8: 314.583771\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 10: 311.584534\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 12: 310.961823\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 14: 310.340393\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 16: 309.720184\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 18: 309.100952\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 20: 308.483307\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 22: 307.866699\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 24: 307.251190\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 26: 306.637421\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 28: 306.024811\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 30: 305.413208\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 32: 304.802704\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 34: 304.193420\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 36: 303.585419\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 38: 302.978943\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 40: 302.373566\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 42: 301.769226\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 44: 301.166351\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 46: 300.564514\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 48: 299.963470\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 50: 299.364044\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 52: 298.765900\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 54: 298.168640\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 56: 297.573090\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 58: 296.978516\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 60: 296.384491\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 62: 295.792389\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 64: 295.201141\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 66: 294.611176\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 68: 294.022552\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 70: 293.435089\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 72: 292.848389\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 74: 292.263275\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 76: 291.679108\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 78: 291.095917\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 80: 290.514618\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 82: 289.933746\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 84: 289.354126\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 86: 288.776245\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 88: 288.198975\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 90: 287.623169\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 92: 287.048157\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 94: 286.474609\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 96: 285.902283\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 98: 285.330536\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Minibatch loss at step 100: 284.760284\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 60.8%\n",
      "Test accuracy: 66.8%\n"
     ]
    }
   ],
   "source": [
    "num_steps = 101\n",
    "num_batches = 2\n",
    "\n",
    "with tf.Session(graph=graph) as session:\n",
    "    tf.initialize_all_variables().run()\n",
    "    print(\"Initialized\")\n",
    "    for step in range(num_steps):\n",
    "        # Pick an offset within the training data, which has been randomized.\n",
    "        # Note: we could use better randomization across epochs.\n",
    "        #offset = (step * batch_size) % (train_labels.shape[0] - batch_size)\n",
    "        offset = step % num_batches\n",
    "        # Generate a minibatch.\n",
    "        batch_data = train_dataset[offset:(offset + batch_size), :]\n",
    "        batch_labels = train_labels[offset:(offset + batch_size), :]\n",
    "        # Prepare a dictionary telling the session where to feed the minibatch.\n",
    "        # The key of the dictionary is the placeholder node of the graph to be fed,\n",
    "        # and the value is the numpy array to feed to it.\n",
    "        feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels, beta_regul : 1e-3}\n",
    "        _, l, predictions = session.run(\n",
    "          [optimizer, loss, train_prediction], feed_dict=feed_dict)\n",
    "        if (step % 2 == 0):\n",
    "            print(\"Minibatch loss at step %d: %f\" % (step, l))\n",
    "            print(\"Minibatch accuracy: %.1f%%\" % accuracy(predictions, batch_labels))\n",
    "            print(\"Validation accuracy: %.1f%%\" % accuracy(\n",
    "            valid_prediction.eval(), valid_labels))\n",
    "    print(\"Test accuracy: %.1f%%\" % accuracy(test_prediction.eval(), test_labels))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since there are far too much parameters and no regularization, the accuracy of the batches is 100%. The generalization capability is poor, as shown in the validation and test accuracy."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "ww3SCBUdlkRc"
   },
   "source": [
    "---\n",
    "Problem 3\n",
    "---------\n",
    "Introduce Dropout on the hidden layer of the neural network. Remember: Dropout should only be introduced during training, not evaluation, otherwise your evaluation results would be stochastic as well. TensorFlow provides `nn.dropout()` for that, but you have to make sure it's only inserted during training.\n",
    "\n",
    "What happens to our extreme overfitting case?\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "num_hidden_nodes = 1024\n",
    "\n",
    "graph = tf.Graph()\n",
    "with graph.as_default():\n",
    "\n",
    "    # Input data. For the training data, we use a placeholder that will be fed\n",
    "    # at run time with a training minibatch.\n",
    "    tf_train_dataset = tf.placeholder(tf.float32,\n",
    "                                    shape=(batch_size, image_size * image_size))\n",
    "    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))\n",
    "    tf_valid_dataset = tf.constant(valid_dataset)\n",
    "    tf_test_dataset = tf.constant(test_dataset)\n",
    "  \n",
    "    # Variables.\n",
    "    weights1 = tf.Variable(tf.truncated_normal([image_size * image_size, num_hidden_nodes]))\n",
    "    biases1 = tf.Variable(tf.zeros([num_hidden_nodes]))\n",
    "    weights2 = tf.Variable(tf.truncated_normal([num_hidden_nodes, num_labels]))\n",
    "    biases2 = tf.Variable(tf.zeros([num_labels]))\n",
    "  \n",
    "    # Training computation.\n",
    "    lay1_train = tf.nn.relu(tf.matmul(tf_train_dataset, weights1) + biases1)\n",
    "    drop1 = tf.nn.dropout(lay1_train, 0.5)\n",
    "    logits = tf.matmul(drop1, weights2) + biases2\n",
    "    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels))\n",
    "    \n",
    "    # Optimizer.\n",
    "    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)\n",
    "  \n",
    "    # Predictions for the training, validation, and test data.\n",
    "    train_prediction = tf.nn.softmax(logits)\n",
    "    lay1_valid = tf.nn.relu(tf.matmul(tf_valid_dataset, weights1) + biases1)\n",
    "    valid_prediction = tf.nn.softmax(tf.matmul(lay1_valid, weights2) + biases2)\n",
    "    lay1_test = tf.nn.relu(tf.matmul(tf_test_dataset, weights1) + biases1)\n",
    "    test_prediction = tf.nn.softmax(tf.matmul(lay1_test, weights2) + biases2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialized\n",
      "Minibatch loss at step 0: 467.479492\n",
      "Minibatch accuracy: 8.6%\n",
      "Validation accuracy: 30.9%\n",
      "Minibatch loss at step 2: 1039.306152\n",
      "Minibatch accuracy: 43.0%\n",
      "Validation accuracy: 38.8%\n",
      "Minibatch loss at step 4: 183.974976\n",
      "Minibatch accuracy: 69.5%\n",
      "Validation accuracy: 56.0%\n",
      "Minibatch loss at step 6: 15.783927\n",
      "Minibatch accuracy: 92.2%\n",
      "Validation accuracy: 68.0%\n",
      "Minibatch loss at step 8: 8.998919\n",
      "Minibatch accuracy: 96.9%\n",
      "Validation accuracy: 67.1%\n",
      "Minibatch loss at step 10: 5.262491\n",
      "Minibatch accuracy: 96.1%\n",
      "Validation accuracy: 65.1%\n",
      "Minibatch loss at step 12: 1.548760\n",
      "Minibatch accuracy: 98.4%\n",
      "Validation accuracy: 66.7%\n",
      "Minibatch loss at step 14: 3.224052\n",
      "Minibatch accuracy: 96.9%\n",
      "Validation accuracy: 66.1%\n",
      "Minibatch loss at step 16: 1.952539\n",
      "Minibatch accuracy: 97.7%\n",
      "Validation accuracy: 65.5%\n",
      "Minibatch loss at step 18: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 65.0%\n",
      "Minibatch loss at step 20: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 64.6%\n",
      "Minibatch loss at step 22: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 64.6%\n",
      "Minibatch loss at step 24: 2.077193\n",
      "Minibatch accuracy: 98.4%\n",
      "Validation accuracy: 67.2%\n",
      "Minibatch loss at step 26: 1.239522\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 66.8%\n",
      "Minibatch loss at step 28: 1.053647\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 65.5%\n",
      "Minibatch loss at step 30: 0.648093\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 66.5%\n",
      "Minibatch loss at step 32: 0.824733\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 66.4%\n",
      "Minibatch loss at step 34: 0.658954\n",
      "Minibatch accuracy: 98.4%\n",
      "Validation accuracy: 67.7%\n",
      "Minibatch loss at step 36: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 67.7%\n",
      "Minibatch loss at step 38: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 67.7%\n",
      "Minibatch loss at step 40: 0.255343\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 67.4%\n",
      "Minibatch loss at step 42: 1.127141\n",
      "Minibatch accuracy: 98.4%\n",
      "Validation accuracy: 68.3%\n",
      "Minibatch loss at step 44: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.3%\n",
      "Minibatch loss at step 46: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.3%\n",
      "Minibatch loss at step 48: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.3%\n",
      "Minibatch loss at step 50: 0.282101\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 69.0%\n",
      "Minibatch loss at step 52: 2.403967\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 68.7%\n",
      "Minibatch loss at step 54: 1.693095\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 67.8%\n",
      "Minibatch loss at step 56: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 67.8%\n",
      "Minibatch loss at step 58: 1.144797\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 68.4%\n",
      "Minibatch loss at step 60: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.4%\n",
      "Minibatch loss at step 62: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.4%\n",
      "Minibatch loss at step 64: 0.671160\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 68.6%\n",
      "Minibatch loss at step 66: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.4%\n",
      "Minibatch loss at step 68: 0.518030\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 68.8%\n",
      "Minibatch loss at step 70: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.8%\n",
      "Minibatch loss at step 72: 0.987952\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 69.4%\n",
      "Minibatch loss at step 74: 1.102341\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 69.1%\n",
      "Minibatch loss at step 76: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.3%\n",
      "Minibatch loss at step 78: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.9%\n",
      "Minibatch loss at step 80: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.9%\n",
      "Minibatch loss at step 82: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 69.2%\n",
      "Minibatch loss at step 84: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 69.2%\n",
      "Minibatch loss at step 86: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.8%\n",
      "Minibatch loss at step 88: 0.998222\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 68.5%\n",
      "Minibatch loss at step 90: 1.814551\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 68.5%\n",
      "Minibatch loss at step 92: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.5%\n",
      "Minibatch loss at step 94: 0.605957\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 68.8%\n",
      "Minibatch loss at step 96: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.8%\n",
      "Minibatch loss at step 98: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 68.8%\n",
      "Test accuracy: 75.2%\n"
     ]
    }
   ],
   "source": [
    "num_steps = 100\n",
    "num_batches = 2\n",
    "\n",
    "with tf.Session(graph=graph) as session:\n",
    "    tf.initialize_all_variables().run()\n",
    "    print(\"Initialized\")\n",
    "    for step in range(num_steps):\n",
    "        # Pick an offset within the training data, which has been randomized.\n",
    "        # Note: we could use better randomization across epochs.\n",
    "        #offset = (step * batch_size) % (train_labels.shape[0] - batch_size)\n",
    "        offset = step % num_batches\n",
    "        # Generate a minibatch.\n",
    "        batch_data = train_dataset[offset:(offset + batch_size), :]\n",
    "        batch_labels = train_labels[offset:(offset + batch_size), :]\n",
    "        # Prepare a dictionary telling the session where to feed the minibatch.\n",
    "        # The key of the dictionary is the placeholder node of the graph to be fed,\n",
    "        # and the value is the numpy array to feed to it.\n",
    "        feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels}\n",
    "        _, l, predictions = session.run(\n",
    "          [optimizer, loss, train_prediction], feed_dict=feed_dict)\n",
    "        if (step % 2 == 0):\n",
    "            print(\"Minibatch loss at step %d: %f\" % (step, l))\n",
    "            print(\"Minibatch accuracy: %.1f%%\" % accuracy(predictions, batch_labels))\n",
    "            print(\"Validation accuracy: %.1f%%\" % accuracy(valid_prediction.eval(), valid_labels))\n",
    "    print(\"Test accuracy: %.1f%%\" % accuracy(test_prediction.eval(), test_labels))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dropout definitely helped, but it is far better to use regularization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "-b1hTz3VWZjw"
   },
   "source": [
    "---\n",
    "Problem 4\n",
    "---------\n",
    "\n",
    "Try to get the best performance you can using a multi-layer model! The best reported test accuracy using a deep network is [97.1%](http://yaroslavvb.blogspot.com/2011/09/notmnist-dataset.html?showComment=1391023266211#c8758720086795711595).\n",
    "\n",
    "One avenue you can explore is to add multiple layers.\n",
    "\n",
    "Another one is to use learning rate decay:\n",
    "\n",
    "    global_step = tf.Variable(0)  # count the number of steps taken.\n",
    "    learning_rate = tf.train.exponential_decay(0.5, global_step, ...)\n",
    "    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)\n",
    " \n",
    " ---\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "num_hidden_nodes1 = 1024\n",
    "num_hidden_nodes2 = 256\n",
    "num_hidden_nodes3 = 128\n",
    "keep_prob = 0.5\n",
    "\n",
    "graph = tf.Graph()\n",
    "with graph.as_default():\n",
    "\n",
    "    # Input data. For the training data, we use a placeholder that will be fed\n",
    "    # at run time with a training minibatch.\n",
    "    tf_train_dataset = tf.placeholder(tf.float32,\n",
    "                                    shape=(batch_size, image_size * image_size))\n",
    "    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))\n",
    "    tf_valid_dataset = tf.constant(valid_dataset)\n",
    "    tf_test_dataset = tf.constant(test_dataset)\n",
    "    global_step = tf.Variable(0)\n",
    "\n",
    "    # Variables.\n",
    "    weights1 = tf.Variable(\n",
    "    tf.truncated_normal(\n",
    "        [image_size * image_size, num_hidden_nodes1],\n",
    "        stddev=np.sqrt(2.0 / (image_size * image_size)))\n",
    "    )\n",
    "    biases1 = tf.Variable(tf.zeros([num_hidden_nodes1]))\n",
    "    weights2 = tf.Variable(\n",
    "    tf.truncated_normal([num_hidden_nodes1, num_hidden_nodes2], stddev=np.sqrt(2.0 / num_hidden_nodes1)))\n",
    "    biases2 = tf.Variable(tf.zeros([num_hidden_nodes2]))\n",
    "    weights3 = tf.Variable(tf.truncated_normal([num_hidden_nodes2, num_hidden_nodes3], stddev=np.sqrt(2.0 / num_hidden_nodes2)))\n",
    "    biases3 = tf.Variable(tf.zeros([num_hidden_nodes3]))\n",
    "    weights4 = tf.Variable(\n",
    "    tf.truncated_normal([num_hidden_nodes3, num_labels], stddev=np.sqrt(2.0 / num_hidden_nodes3)))\n",
    "    biases4 = tf.Variable(tf.zeros([num_labels]))\n",
    "  \n",
    "    # Training computation.\n",
    "    lay1_train = tf.nn.relu(tf.matmul(tf_train_dataset, weights1) + biases1)\n",
    "    lay2_train = tf.nn.relu(tf.matmul(lay1_train, weights2) + biases2)\n",
    "    lay3_train = tf.nn.relu(tf.matmul(lay2_train, weights3) + biases3)\n",
    "    logits = tf.matmul(lay3_train, weights4) + biases4\n",
    "    loss = tf.reduce_mean(\n",
    "    tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels))\n",
    "  \n",
    "    # Optimizer.\n",
    "    learning_rate = tf.train.exponential_decay(0.5, global_step, 4000, 0.65, staircase=True)\n",
    "    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)\n",
    "  \n",
    "    # Predictions for the training, validation, and test data.\n",
    "    train_prediction = tf.nn.softmax(logits)\n",
    "    lay1_valid = tf.nn.relu(tf.matmul(tf_valid_dataset, weights1) + biases1)\n",
    "    lay2_valid = tf.nn.relu(tf.matmul(lay1_valid, weights2) + biases2)\n",
    "    lay3_valid = tf.nn.relu(tf.matmul(lay2_valid, weights3) + biases3)\n",
    "    valid_prediction = tf.nn.softmax(tf.matmul(lay3_valid, weights4) + biases4)\n",
    "    lay1_test = tf.nn.relu(tf.matmul(tf_test_dataset, weights1) + biases1)\n",
    "    lay2_test = tf.nn.relu(tf.matmul(lay1_test, weights2) + biases2)\n",
    "    lay3_test = tf.nn.relu(tf.matmul(lay2_test, weights3) + biases3)\n",
    "    test_prediction = tf.nn.softmax(tf.matmul(lay3_test, weights4) + biases4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialized\n",
      "Minibatch loss at step 0: 2.459811\n",
      "Minibatch accuracy: 8.6%\n",
      "Validation accuracy: 36.4%\n",
      "Minibatch loss at step 500: 0.569909\n",
      "Minibatch accuracy: 81.2%\n",
      "Validation accuracy: 85.7%\n",
      "Minibatch loss at step 1000: 0.365850\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 87.7%\n",
      "Minibatch loss at step 1500: 0.413508\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 88.1%\n",
      "Minibatch loss at step 2000: 0.352726\n",
      "Minibatch accuracy: 89.8%\n",
      "Validation accuracy: 89.2%\n",
      "Minibatch loss at step 2500: 0.361857\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 89.2%\n",
      "Minibatch loss at step 3000: 0.227793\n",
      "Minibatch accuracy: 92.2%\n",
      "Validation accuracy: 89.3%\n",
      "Minibatch loss at step 3500: 0.217227\n",
      "Minibatch accuracy: 93.0%\n",
      "Validation accuracy: 89.2%\n",
      "Minibatch loss at step 4000: 0.405572\n",
      "Minibatch accuracy: 86.7%\n",
      "Validation accuracy: 89.8%\n",
      "Minibatch loss at step 4500: 0.123727\n",
      "Minibatch accuracy: 96.1%\n",
      "Validation accuracy: 90.8%\n",
      "Minibatch loss at step 5000: 0.191225\n",
      "Minibatch accuracy: 93.8%\n",
      "Validation accuracy: 90.5%\n",
      "Minibatch loss at step 5500: 0.362751\n",
      "Minibatch accuracy: 87.5%\n",
      "Validation accuracy: 90.5%\n",
      "Minibatch loss at step 6000: 0.129323\n",
      "Minibatch accuracy: 96.1%\n",
      "Validation accuracy: 90.4%\n",
      "Minibatch loss at step 6500: 0.350460\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 90.3%\n",
      "Minibatch loss at step 7000: 0.204761\n",
      "Minibatch accuracy: 92.2%\n",
      "Validation accuracy: 90.0%\n",
      "Minibatch loss at step 7500: 0.172040\n",
      "Minibatch accuracy: 94.5%\n",
      "Validation accuracy: 90.7%\n",
      "Minibatch loss at step 8000: 0.092611\n",
      "Minibatch accuracy: 96.9%\n",
      "Validation accuracy: 90.7%\n",
      "Minibatch loss at step 8500: 0.134734\n",
      "Minibatch accuracy: 96.1%\n",
      "Validation accuracy: 90.9%\n",
      "Minibatch loss at step 9000: 0.139563\n",
      "Minibatch accuracy: 96.1%\n",
      "Validation accuracy: 91.0%\n",
      "Minibatch loss at step 9500: 0.120939\n",
      "Minibatch accuracy: 95.3%\n",
      "Validation accuracy: 91.1%\n",
      "Minibatch loss at step 10000: 0.114840\n",
      "Minibatch accuracy: 97.7%\n",
      "Validation accuracy: 90.6%\n",
      "Test accuracy: 95.8%\n"
     ]
    }
   ],
   "source": [
    "# 10000 steps is more than enough\n",
    "\n",
    "num_steps = 10001\n",
    "\n",
    "with tf.Session(graph=graph) as session:\n",
    "    tf.initialize_all_variables().run()\n",
    "    print(\"Initialized\")\n",
    "    for step in range(num_steps):\n",
    "        # Pick an offset within the training data, which has been randomized.\n",
    "        # Note: we could use better randomization across epochs.\n",
    "        offset = (step * batch_size) % (train_labels.shape[0] - batch_size)\n",
    "        # Generate a minibatch.\n",
    "        batch_data = train_dataset[offset:(offset + batch_size), :]\n",
    "        batch_labels = train_labels[offset:(offset + batch_size), :]\n",
    "        # Prepare a dictionary telling the session where to feed the minibatch.\n",
    "        # The key of the dictionary is the placeholder node of the graph to be fed,\n",
    "        # and the value is the numpy array to feed to it.\n",
    "        feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels}\n",
    "        _, l, predictions = session.run(\n",
    "          [optimizer, loss, train_prediction], feed_dict=feed_dict)\n",
    "        if (step % 500 == 0):\n",
    "            print(\"Minibatch loss at step %d: %f\" % (step, l))\n",
    "            print(\"Minibatch accuracy: %.1f%%\" % accuracy(predictions, batch_labels))\n",
    "            print(\"Validation accuracy: %.1f%%\" % accuracy(valid_prediction.eval(), valid_labels))\n",
    "    print(\"Test accuracy: %.1f%%\" % accuracy(test_prediction.eval(), test_labels))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "default_view": {},
   "name": "3_regularization.ipynb",
   "provenance": [],
   "version": "0.3.2",
   "views": {}
  },
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
